use chrono::{DateTime, NaiveDateTime, Utc};
use sea_orm::{
    ActiveValue, ColumnTrait, DatabaseConnection, DbErr, EntityOrSelect, EntityTrait,
    IntoActiveModel, Order, PaginatorTrait, QueryFilter, QueryOrder, QuerySelect,
};
use sky_common::constant::{self, order};
use sky_pojo::{
    dto,
    entities::{order_detail, orders},
};

pub async fn insert(
    db: &DatabaseConnection,
    order: orders::ActiveModel,
) -> Result<orders::Model, sea_orm::DbErr> {
    orders::Entity::insert(order).exec_with_returning(db).await
}

pub async fn order_detail_insert_batch(
    db: &DatabaseConnection,
    order_detail_vec: Vec<order_detail::ActiveModel>,
) -> Result<order_detail::Model, sea_orm::DbErr> {
    order_detail::Entity::insert_many(order_detail_vec)
        .exec_with_returning(db)
        .await
}

pub async fn get_by_number_and_user_id(
    db: &DatabaseConnection,
    order_number: String,
    user_id: i64,
) -> Result<Option<orders::Model>, sea_orm::DbErr> {
    orders::Entity
        .select()
        .filter(orders::Column::Number.eq(order_number))
        .filter(orders::Column::UserId.eq(user_id))
        .one(db)
        .await
}

pub async fn update(
    db: &DatabaseConnection,
    order_number: String,
    order: orders::ActiveModel,
) -> Result<(), String> {
    match orders::Entity::update_many()
        .set(order.clone())
        .filter(orders::Column::Number.eq(order_number))
        .exec(db)
        .await
    {
        Ok(_) => return Ok(()),
        Err(e) => return Err(e.to_string()),
    }
}

pub async fn page_query(
    db: &DatabaseConnection,
    dto: dto::order::OrdersPageQueryDTO,
) -> Result<Vec<orders::Model>, sea_orm::DbErr> {
    let mut query = orders::Entity::find();

    // 动态条件添加
    if let Some(ref num) = dto.number {
        query = query.filter(orders::Column::Number.like(format!("%{}%", num)));
    }

    if let Some(ref ph) = dto.phone {
        query = query.filter(orders::Column::Phone.like(format!("%{}%", ph)));
    }

    if let Some(id) = dto.user_id {
        query = query.filter(orders::Column::UserId.eq(id));
    }

    if let Some(st) = dto.status {
        query = query.filter(orders::Column::Status.eq(st));
    }

    if let Some(beg) = dto.begin_time {
        query = query.filter(orders::Column::OrderTime.gte(beg));
    }

    if let Some(end) = dto.end_time {
        query = query.filter(orders::Column::OrderTime.lte(end));
    }

    // 排序
    query = query.order_by(orders::Column::OrderTime, Order::Desc);

    // 执行查询
    query.all(db).await
}

pub async fn order_detail_get_by_order_id(
    db: &DatabaseConnection,
    order_id: i64,
) -> Result<Vec<order_detail::Model>, sea_orm::DbErr> {
    order_detail::Entity::find()
        .filter(order_detail::Column::OrderId.eq(order_id))
        .all(db)
        .await
}

pub async fn get_by_id(
    db: &DatabaseConnection,
    id: i64,
) -> Result<Option<orders::Model>, sea_orm::DbErr> {
    orders::Entity::find()
        .filter(orders::Column::Number.eq(id))
        .one(db)
        .await
}

pub async fn count_status(db: &DatabaseConnection, status: i32) -> Result<u64, String> {
    orders::Entity::find()
        .filter(orders::Column::Status.eq(status))
        .count(db)
        .await
        .map_err(|e| e.to_string())
}

pub async fn get_by_status_and_ordertime_lt(
    db: &DatabaseConnection,
    status: i32,
    order_time: NaiveDateTime,
) -> Result<Vec<orders::Model>, DbErr> {
    orders::Entity::find()
        .filter(orders::Column::Status.eq(status))
        .filter(orders::Column::OrderTime.eq(order_time))
        .all(db)
        .await
}

pub async fn get_status_by_id(db: &DatabaseConnection, id: String) -> Result<Vec<i32>, DbErr> {
    orders::Entity::find()
        .select_only()
        .column(orders::Column::Status)
        .filter(orders::Column::Number.eq(id))
        .into_tuple::<i32>()
        .all(db)
        .await
}
